# Лекция: SOLID принципы в Java

SOLID - это акроним, обозначающий пять основных принципов объектно-ориентированного программирования и проектирования:

1. **S - Single Responsibility Principle (Принцип единственной ответственности)**: Каждый класс должен иметь только одну причину для изменения. Это означает, что класс должен иметь только одну задачу или ответственность.

2. **O - Open/Closed Principle (Принцип открытости/закрытости)**: Классы должны быть открыты для расширения, но закрыты для изменения. Это означает, что мы должны быть в состоянии добавлять новую функциональность без изменения существующего кода.

3. **L - Liskov Substitution Principle (Принцип подстановки Барбары Лисков)**: Подклассы должны быть заменяемыми на их базовые классы без изменения корректности программы. Это означает, что объекты в программе можно заменить их подтипами без изменения правильности выполнения программы.

4. **I - Interface Segregation Principle (Принцип разделения интерфейса)**: Клиенты не должны зависеть от интерфейсов, которые они не используют. Это означает, что большие интерфейсы следует разбивать на меньшие и более конкретные, чтобы клиенты будут использовать только те интерфейсы, которые им требуются.

5. **D - Dependency Inversion Principle (Принцип инверсии зависимостей)**: Зависимости на конкретные модули должны заменяться на абстракции. Это означает, что высокоуровневые модули не должны зависеть от низкоуровневых модулей. Оба должны зависеть от абстракций.

---

# Практические задания

1. **Создайте класс `Printer`, который нарушает принцип единственной ответственности, и исправьте его.** (Сложность: 2/5)
```java
public class Printer {
    public void print(Document document) {
        // печать документа
    }

    public void staple(Document document) {
        // скрепление документа
    }
}

public class Printer {
    public void print(Document document) {
        // печать документа
    }
}

public class Stapler {
    public void staple(Document document) {
        // скрепление документа
    }
}
```

2. **Создайте класс `Rectangle` и класс `Square`, который нарушает принцип открытости/закрытости, и исправьте его.** (Сложность: 3/5)
```java
public class Rectangle {
    protected int width;
    protected int height;

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}

public class Square extends Rectangle {
    public void setWidth(int width) {
        this.width = width;
        this.height = width;
    }

    public void setHeight(int height) {
        this.width = height;
        this.height = height;
    }
}

public class Rectangle {
    protected int width;
    protected int height;

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}

public class Square {
    protected int size;

    public void setSize(int size) {
        this.size = size;
    }
}
```

3. **Создайте класс `Bird` и класс `Penguin`, который нарушает принцип подстановки Барбары Лисков, и исправьте его.** (Сложность: 3/5)
```java
public class Bird {
    public void fly() {
        // летать
    }
}

public class Penguin extends Bird {
    public void fly() {
        throw new UnsupportedOperationException("Penguins can't fly");
    }
}

public class Bird {
    public void fly() {
        // летать
    }
}

public class Penguin extends Bird {
    // Не переопределяет метод fly
}
```

4. **Создайте интерфейс `Worker`, который нарушает принцип разделения интерфейса, и исправьте его.** (Сложность: 2/5)
```java
public interface Worker {
    void work();
    void eat();
}

public interface Worker {
    void work();
}

public interface Eater {
    void eat();
}
```

5. **Создайте класс `DatabaseService`, который нарушает принцип инверсии зависимостей, и исправьте его.** (Сложность: 3/5)
```java
public class DatabaseService {
    private MySQLDatabase database;

    public void setDatabase(MySQLDatabase database) {
        this.database = database;
    }

    public void save(String data) {
        database.save(data);
    }
}

public interface Database {
    void save(String data);
}

public class MySQLDatabase implements Database {
    public void save(String data) {
        // сохранить данные
    }
}

public class DatabaseService {
    private Database database;

    public void setDatabase(Database database) {
        this.database = database;
    }

    public void save(String data) {
        database.save(data);
    }
}
```